﻿using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;
using VisionCloud.Core.Model.Ms;
using VisionCloud.Domain.Common;
using VisionCloud.Domain.DtoModel.Ms;
using VisionCloud.Domain.Repository.Interface.Ms;
using VisionCloud.Domain.UnitOfWork;
using VisionCloud.Utility;
using VisionCloud.Domain.DtoModel.Sys;

namespace VisionCloud.Service.Ms
{
    public class FileService
    {
        public IUnitOfWork UnitOfWork { get; set; }
        public IMsUpdatePkgRepository MsUpdatePkgRepository { get; set; }
        public IMsRobotRepository MsRobotRepository { get; set; }

        public async Task UploadUpdatePkgAsync(UpdatePkgFile data)
        {
            StringBuilder sbMD5 = new StringBuilder();
            string FolderPath = GetFileFolder(data.Type);
            if (data.file.Length > 0)
            {

                var fileName = data.file.FileName;

                sbMD5.Clear();

                var filePath = Path.Combine(FolderPath, fileName);

                if (System.IO.File.Exists(filePath))
                {
                    System.IO.File.Delete(filePath);
                }

                using (FileStream stream = System.IO.File.Create(filePath))
                {
                    await data.file.CopyToAsync(stream);
                    await stream.FlushAsync();
                    sbMD5.Append(FileInfoUtil.GetMD5Hash(stream));
                }
                var updatePkg = new MsUpdatePkg()
                {
                    CreatedDate = DateTime.Now,
                    CreatedBy = data.operateInfo.Id,
                    LastUpdatedDate = DateTime.Now,
                    LastUpdatedBy = data.operateInfo.Id,

                    Os = data.OS,
                    Version = data.Version,
                    Mode = Convert.ToInt32(data.Mode),
                    Notes = data.Notes,

                    Url = fileName,
                    Size = data.file.Length,
                    Md5 = sbMD5.ToString()
                };
                MsUpdatePkgRepository.Add(updatePkg);
                
            }
            await UnitOfWork.SaveChangesAsync();
        }

        #region Model集合
        public class UpdatePkgFile
        {
            public string OS { get; set; }
            public string Version { get; set; }
            public string Mode { get; set; }
            public string Notes { get; set; }

            public FileTypeEnum Type = FileTypeEnum.Vesion;
            public IFormFile file { get; set; }
            public OperateInfo operateInfo { get; set; }
        }
        public class FileModel1
        {
            /// <summary>
            /// FileName
            /// </summary>
            public string Name { get; set; }
            /// <summary>
            /// 文件
            /// </summary>
            public IFormFileCollection files { get; set; }
        }

        #endregion

        #region 基础组件


        /// <summary>
        /// 存储多文件
        /// </summary>
        /// <param name="Data"></param>
        /// <returns></returns>
        //public async Task UploadAndSaveFileCore(FileModel Data)
        //{
        //    if (!Directory.Exists(Data.Path))
        //    {
        //        Directory.CreateDirectory(Data.Path);
        //    }
        //    foreach (var file in Data.files)
        //    {
        //        if (file.Length > 0)
        //        {
        //            var filePath = Path.Combine(Data.Path, file.FileName);
        //            //伪覆盖性存储
        //            if (System.IO.File.Exists(filePath))
        //            {
        //                System.IO.File.Delete(filePath);
        //            }
        //            using (FileStream stream = System.IO.File.Create(filePath))
        //            {
        //                await file.CopyToAsync(stream);
        //                await stream.FlushAsync();
        //            }
        //        }
        //    }
        //}
        public async Task SaveFilesAsyncCore() 
        { 
            
        }
        #endregion

        public async Task UploadFilesAsync(IFormCollection formCollection, OperateInfo operateInfo)
        {
            FileTypeEnum type = (FileTypeEnum)Enum.Parse(typeof(FileTypeEnum), formCollection["Type"]);
            switch (type)
            {
                case FileTypeEnum.Defalut:
                    throw new OperationException("操作失败:找不到文件信息");
                case FileTypeEnum.Vesion:
                    IFormFileCollection files = formCollection.Files;
                    string version = formCollection["Version"];
                    if (files.Count == 0)
                    {
                        throw new OperationException("操作失败:找不到文件信息");
                    }

                    if (!Regex.IsMatch(version, @"^\d+?\.\d+?\.\d+?$", RegexOptions.IgnoreCase))
                    {
                        throw new OperationException("操作失败:请确保版本号如格式:1.2.1");
                    }
                    foreach (var file in files)
                    {
                        if (file.Length > 0)
                        {
                            var fileName = file.FileName;
                            if (!Regex.IsMatch(fileName, @"^[vV]\d+?\.\d+?\.\d+?_(win|linux)\.zip$",
                                RegexOptions.IgnoreCase))
                            {
                                throw new OperationException(
                                    "操作失败:文件名称不符合规则，上传来的升级包必须命名为 vx.y.z_win.zip 或者 vx.y.z_linux.zip");
                            }
                        }
                        else
                            throw new OperationException("操作失败: 文件Size为0,请核实文件是否选择正确");
                    }
                    await UploadAndSaveAsyncCore(formCollection, operateInfo);
                    break;
                default:
                    throw new OperationException("未知的文件操作类型");
            }
        }
        public async Task RobotUploadFilesAsync(IFormCollection formCollection, OperateInfo operateInfo)
        {
            //获取参数
            string id = formCollection["ID"];
            string token = formCollection["Token"];
            FileTypeEnum type = (FileTypeEnum)Enum.Parse(typeof(FileTypeEnum), formCollection["Type"]);


            if (!MsRobotRepository.Any(p => p.RobotId == id && p.Token == token))
            {
                throw new OperationException("操作失败:令牌验证失败");
            }
            if (type != FileTypeEnum.RobotFile)
            {
                throw new OperationException("操作失败:Type类型错误");
            }
            IFormFileCollection files = formCollection.Files;
            if (files.Count == 0)
            {
                throw new OperationException("操作失败:找不到文件信息");
            }

            var contentRootPath = ConfigureHandle.ContentRootPath;
            string fileFolder = formCollection.ContainsKey("ChildFolder") ? Path.Combine(contentRootPath, "FileFolder", id, formCollection["ChildFolder"]) : fileFolder = Path.Combine(contentRootPath, "FileFolder", id);
            Regex regex = new Regex(@"^([a-zA-Z]:\\)?[^\/\:\*\?\""\<\>\|\,]*$");
            Match m = regex.Match(fileFolder);
            if (!m.Success)
            {
                throw new OperationException("操作失败:非法的保存路径");
            }
            await UploadAndSaveAsyncCore(formCollection, operateInfo);
        }

        /// <summary>
        /// 上传并保存
        /// </summary>
        /// <param name="files"></param>
        /// <param name="sbMD5"></param>
        /// <param name="os"></param>
        /// <param name="version"></param>
        /// <param name="mode"></param>
        /// <param name="notes"></param>
        /// <returns></returns>
        private async Task UploadAndSaveAsyncCore(IFormCollection formCollection, OperateInfo operateInfo)
        {
            StringBuilder sbMD5 = new StringBuilder();
            string os = formCollection["OS"];
            string version = formCollection["Version"];
            string mode = formCollection["Mode"];
            string notes = formCollection["notes"];
            IFormFileCollection files = formCollection.Files;
            long size = files.Sum(f => f.Length);

            FileTypeEnum type = (FileTypeEnum)Enum.Parse(typeof(FileTypeEnum), formCollection["Type"]);


            var contentRootPath = ConfigureHandle.ContentRootPath;

            var fileFolder = "";
            if (type == FileTypeEnum.Defalut)
                fileFolder = Path.Combine(contentRootPath, "FileFolder", "WebFile");
            else if (type == FileTypeEnum.Vesion)
                fileFolder = Path.Combine(contentRootPath, "FileFolder", "pkg");
            else if (type == FileTypeEnum.RobotFile)
            {
                string id = formCollection["ID"];
                if (formCollection.ContainsKey("ChildFolder"))
                {
                    string path = formCollection["ChildFolder"];
                    fileFolder = Path.Combine(contentRootPath, "FileFolder", id, path);
                }
                else
                    fileFolder = Path.Combine(contentRootPath, "FileFolder", id);
            }
            if (!Directory.Exists(fileFolder))
            {
                Directory.CreateDirectory(fileFolder);
            }

            foreach (var file in files)
            {
                if (file.Length > 0)
                {

                    var fileName = file.FileName;

                    sbMD5.Clear();

                    var filePath = Path.Combine(fileFolder, fileName);

                    if (System.IO.File.Exists(filePath))
                    {
                        System.IO.File.Delete(filePath);
                    }

                    using (FileStream stream = System.IO.File.Create(filePath))
                    {
                        await file.CopyToAsync(stream);
                        await stream.FlushAsync();
                        sbMD5.Append(FileInfoUtil.GetMD5Hash(stream));
                    }
                    if (type == FileTypeEnum.Vesion)
                    {
                        var updatePkg = new MsUpdatePkg()
                        {
                            CreatedDate = DateTime.Now,
                            CreatedBy = operateInfo.Id,
                            LastUpdatedDate = DateTime.Now,
                            LastUpdatedBy = operateInfo.Id,

                            Os = os,
                            Version = version,
                            Mode = Convert.ToInt32(mode),
                            Notes = notes,

                            Url = fileName,
                            Size = file.Length,
                            Md5 = sbMD5.ToString()
                        };
                        MsUpdatePkgRepository.Add(updatePkg);
                    }
                }
                await UnitOfWork.SaveChangesAsync();
            }
        }

        public async Task UploadAndSaveAsync(IFormCollection formCollection, OperateInfo operateInfo)
        {
            StringBuilder sbMD5 = new StringBuilder();
            string os = formCollection["OS"];
            string version = formCollection["Version"];
            string mode = formCollection["Mode"];
            string notes = formCollection["notes"];
            IFormFileCollection files = formCollection.Files;
            long size = files.Sum(f => f.Length);

            FileTypeEnum type = (FileTypeEnum)Enum.Parse(typeof(FileTypeEnum), formCollection["Type"]);

            var contentRootPath = ConfigureHandle.ContentRootPath;
            var fileFolder = "";
            if (type == FileTypeEnum.Defalut)
                fileFolder = Path.Combine(contentRootPath, "FileFolder", "WebFile");
            else if (type == FileTypeEnum.Vesion)
                fileFolder = Path.Combine(contentRootPath, "FileFolder", "pkg");
            else if (type == FileTypeEnum.RobotFile)
            {
                string id = formCollection["ID"];
                if (formCollection.ContainsKey("ChildFolder"))
                {
                    string path = formCollection["ChildFolder"];
                    fileFolder = Path.Combine(contentRootPath, "FileFolder", id, path);
                }
                else
                    fileFolder = Path.Combine(contentRootPath, "FileFolder", id);
            }
            if (!Directory.Exists(fileFolder))
            {
                Directory.CreateDirectory(fileFolder);
            }

            foreach (var file in files)
            {
                if (file.Length > 0)
                {
                    var fileName = file.FileName;

                    sbMD5.Clear();

                    var filePath = Path.Combine(fileFolder, fileName);

                    if (System.IO.File.Exists(filePath))
                    {
                        System.IO.File.Delete(filePath);
                    }

                    using (FileStream stream = System.IO.File.Create(filePath))
                    {
                        await file.CopyToAsync(stream);
                        await stream.FlushAsync();
                        sbMD5.Append(FileInfoUtil.GetMD5Hash(stream));
                    }
                    if (type == FileTypeEnum.Vesion)
                    {
                        //todo 这段代码应该放到仓储层执行
                        var updatePkg = new MsUpdatePkg()
                        {
                            CreatedDate = DateTime.Now,
                            CreatedBy = operateInfo.Id,
                            LastUpdatedDate = DateTime.Now,
                            LastUpdatedBy = operateInfo.Id,

                            Os = os,
                            Version = version,
                            Mode = Convert.ToInt32(mode),
                            Notes = notes,

                            Url = fileName,
                            Size = file.Length,
                            Md5 = sbMD5.ToString()
                        };
                        MsUpdatePkgRepository.Add(updatePkg);
                    }
                }
               await UnitOfWork.SaveChangesAsync();
            }
        }


        public async Task<ValueTuple<Stream, string, string>> RobotDownload(IFormCollection formCollection)
        {
            //获取参数
            string id = formCollection["ID"];//BZL-MEASURE-0031
            string token = formCollection["Token"];//a212efec0d21356745edfab23e
            string fileName = formCollection["FileName"];
            FileTypeEnum type = (FileTypeEnum)Enum.Parse(typeof(FileTypeEnum), formCollection["Type"]);

            if (!MsRobotRepository.Any(p => p.RobotId == id && p.Token == token))
                throw new OperationException("操作失败:令牌验证失败");

            var contentRootPath = ConfigureHandle.ContentRootPath;
            var fileFolder = "";
            if (type == FileTypeEnum.Defalut)
                throw new OperationException("操作失败:暂不支持获取该类型文件");
            else if (type == FileTypeEnum.Vesion)
                fileFolder = Path.Combine(contentRootPath, "FileFolder", "pkg");
            else if (type == FileTypeEnum.RobotFile)
            {
                if (formCollection.ContainsKey("ChildFolder"))
                {
                    string path = formCollection["ChildFolder"];
                    fileFolder = Path.Combine(contentRootPath, "FileFolder", id, path);
                }
                else
                    fileFolder = Path.Combine(contentRootPath, "FileFolder", id);
            }
            else
                throw new OperationException("操作失败:暂不支持获取该类型文件");

            var fillFullName = Path.Combine(fileFolder, fileName);
            if (!System.IO.File.Exists(fillFullName))
                throw new OperationException("操作失败:指定文件不存在");


            var stream = System.IO.File.OpenRead(fillFullName);
            string fileExt = Path.GetExtension(fileName);

            return (stream, fileName, fileExt);
        }

        public async Task<ValueTuple<Stream, string, string>> Download(QueryDownload queryDownload)
        {
            string fileName = queryDownload.fileName;
            FileTypeEnum type = queryDownload.Type;

            var contentRootPath = ConfigureHandle.ContentRootPath;
            var fileFolder = "";
            if (type == FileTypeEnum.Defalut)
                fileFolder = Path.Combine(contentRootPath, "FileFolder", "WebFile");
            else if (type == FileTypeEnum.Vesion)
                fileFolder = Path.Combine(contentRootPath, "FileFolder", "pkg");
            else if (type == FileTypeEnum.RobotFile)
                throw new OperationException("操作失败:暂不支持获取该类型文件");
            else
                throw new OperationException("操作失败:暂不支持获取该类型文件");
            //var fileFolder = Path.Combine(_hostingEnvironment.ContentRootPath, "FileFolder", "pkg");
            var fillFullName = Path.Combine(fileFolder, fileName);
            if (!System.IO.File.Exists(fillFullName))
                throw new OperationException("操作失败:指定文件不存在");

            var stream = System.IO.File.OpenRead(fillFullName);
            //D:\Cloud\bluepivot\webapp\VisionCloud\VisionCloud\pkg
            string fileExt = Path.GetExtension(fileName);
            return (stream, fileName, fileExt);
        }
    }
}